import asyncio
import json
import os
import sys
import urllib
from configparser import ConfigParser

import aioredis
import re
from tornado import gen

sys.path.append(os.path.abspath('../'))
from baseHandler import init_logger, PayHandler, Application, http_result
from channel.channel_alipay import AliPay


class NotiHandler(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('SUCCESS')

    @gen.coroutine
    def post(self):
        logger.info(self.request.body)
        # data = json.loads(self.request.body.decode("utf-8"), parse_float=str)
        data = dict(urllib.parse.parse_qsl(self.request.body.decode('utf-8')))

        sign = data.pop('sign')
        logger.info(data)
        check_sign = alipay.rsa_verify(data, sign)
        logger.info(check_sign)

        self.write("success")
        self.finish()
        logger.info(data)
        logger.info("通知|流水号%s|支付结果%s", data["out_trade_no"], data["trade_status"])
        if 'receipt_amount' in data:
            amount = float(data["receipt_amount"]) * 100
        else:
            amount = ""
        if data["trade_status"] == "TRADE_SUCCESS":
            orderstate = "0"
        else:
            orderstate = "1"
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': data["out_trade_no"],
                "ORDERSTATE": orderstate,
                "OPMONEY": str(amount),
                "NOTIFYINFO": data['trade_no'],
            }
        }
        # 发送到核心程序
        result = yield from self.pay_core("PAY_ALIPAY_NOTIFY", input_json)
        logger.info(result)
        notifyurl = result.get("NOTIFIYURL", "")

        if notifyurl:
            merchantid = result.get("MERCHANTID")
            res = yield self.merchant_exit(merchantid=merchantid)
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                logger.info(rsp.body)
                # content = rsp.body.upper()
                if rsp.code == 200 and rsp.body in (b'SUCCESS', b'success'):
                    logger.info("%s|%s收到下游成功应答|订单号%s", i, data["out_trade_no"], result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s|%s未收到下游成功应答|订单号%s", i, data["out_trade_no"], result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10 * (i + 1))


class ZfjNotiHandler(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('OK')

    @gen.coroutine
    def post(self):
        logger.info(self.request.body)
        # data = json.loads(self.request.body.decode("utf-8"), parse_float=str)
        data = dict(urllib.parse.parse_qsl(self.request.body.decode('utf-8')))

        self.write("OK")
        self.finish()
        logger.info(data)
        logger.info("通知|流水号%s|支付结果%s", data["orderid"], data["returncode"])
        if 'amount' in data:
            amount = float(data["amount"]) * 100
        else:
            amount = ""
        if data["returncode"] == "00":
            orderstate = "0"
        else:
            orderstate = "1"
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': data["orderid"],
                "ORDERSTATE": orderstate,
                "OPMONEY": str(int(amount)),
                "NOTIFYINFO": data['transaction_id'],
            }
        }
        # 发送到核心程序
        logger.info(input_json)
        result = yield from self.pay_core("PAY_ALIPAY_NOTIFY", input_json)
        logger.info(result)
        notifyurl = result.get("NOTIFIYURL", "")

        if notifyurl:
            merchantid = result.get("MERCHANTID")
            res = yield self.merchant_exit(merchantid=merchantid)
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                logger.info(rsp.body)
                # content = rsp.body.upper()
                if rsp.code == 200 and rsp.body in (b'SUCCESS', b'success'):
                    logger.info("%s|%s收到下游成功应答|订单号%s", i, data["orderid"], result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s|%s未收到下游成功应答|订单号%s", i, data["orderid"], result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10 * (i + 1))


class WsfNotiHandler(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('success')

    @gen.coroutine
    def post(self):
        logger.info(self.request.body)

        # data = json.loads(self.request.body.decode("utf-8"), parse_float=str)
        # data = dict(urllib.parse.parse_qsl(self.request.body.decode('utf-8')))

        self.write("success")
        self.finish()
        # logger.info(data)
        args = re.findall('name="(.*)"[\r\n]+(.*)\r[\r\n]+-', self.request.body.decode())
        data = dict(args)
        amount = data.get("total_fee", 0)
        outer_orderno = data.get("sdorderno")
        payinfo = data.get("sdpayno")
        status = data.get("status")
        amount = int(float(amount) * 100)
        if status == "1":
            orderstate = "0"
        else:
            orderstate = "1"
        logger.info("通知|流水号%s|支付结果%s", outer_orderno, orderstate)

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': outer_orderno,
                "ORDERSTATE": orderstate,
                "OPMONEY": str(amount),
                "NOTIFYINFO": payinfo,
            }
        }
        # 发送到核心程序
        logger.info(input_json)
        result = yield from self.pay_core("PAY_ALIPAY_NOTIFY", input_json)
        logger.info(result)
        notifyurl = result.get("NOTIFIYURL", "")

        if notifyurl:
            merchantid = result.get("MERCHANTID")
            res = yield self.merchant_exit(merchantid=merchantid)
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                logger.info(rsp.body)
                # content = rsp.body.upper()
                if rsp.code == 200 and rsp.body in (b'SUCCESS', b'success'):
                    logger.info("%s|%s收到下游成功应答|订单号%s", i, outer_orderno, result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s|%s未收到下游成功应答|订单号%s", i, outer_orderno, result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10 * (i + 1))


class HJNotiHandler(PayHandler):
    def get(self):
        logger.info(self.request.arguments)
        self.write('success')

    @gen.coroutine
    def post(self):
        logger.info(self.request.body)

        # data = json.loads(self.request.body.decode("utf-8"), parse_float=str)
        # data = dict(urllib.parse.parse_qsl(self.request.body.decode('utf-8')))

        self.write("success")
        self.finish()
        # logger.info(data)
        args = re.findall('name="(.*)"[\r\n]+(.*)\r[\r\n]+-', self.request.body.decode())
        data = dict(args)
        amount = data.get("total_fee", 0)
        outer_orderno = data.get("sdorderno")
        payinfo = data.get("sdpayno")
        status = data.get("status")
        amount = int(float(amount) * 100)
        if status == "1":
            orderstate = "0"
        else:
            orderstate = "1"
        logger.info("通知|流水号%s|支付结果%s", outer_orderno, orderstate)

        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "NOTI",
            "FUNCCODE": "100201",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                'OUTERORDERNO': outer_orderno,
                "ORDERSTATE": orderstate,
                "OPMONEY": str(amount),
                "NOTIFYINFO": payinfo,
            }
        }
        # 发送到核心程序
        logger.info(input_json)
        result = yield from self.pay_core("PAY_ALIPAY_NOTIFY", input_json)
        logger.info(result)
        notifyurl = result.get("NOTIFIYURL", "")

        if notifyurl:
            merchantid = result.get("MERCHANTID")
            res = yield self.merchant_exit(merchantid=merchantid)
            for i in range(5):
                notify_data = {
                    "ordernumber": result["MERCHANTORDERNO"],
                    "respcode": result["ORDERSTATE"],
                    "merchantid": merchantid,
                    "amount": result["OPMONEY"],
                    "businesstime": result["RESPTIME"]
                }

                request_obj = self.niti_data(notify_data, result)
                rsp = yield http_result(notifyurl, request_obj, model='urlencode')
                logger.info(rsp.body)
                # content = rsp.body.upper()
                if rsp.code == 200 and rsp.body in (b'SUCCESS', b'success'):
                    logger.info("%s|%s收到下游成功应答|订单号%s", i, outer_orderno, result["MERCHANTORDERNO"])
                    noti = yield from self.pay_core("PAY_ALIPAY_NOTIFY_RES", {
                        "REQINFO": {"MERCHANTID": merchantid, "MERCHANTORDERNO": result["MERCHANTORDERNO"]}})
                    logger.debug(noti)
                    break
                else:
                    logger.info("%s|%s未收到下游成功应答|订单号%s", i, outer_orderno, result["MERCHANTORDERNO"])
                    yield from asyncio.sleep(10 * (i + 1))

if __name__ == "__main__":
    application = Application([
        (r"/noti/alipay", NotiHandler),
        (r"/noti/zhifujia", ZfjNotiHandler),
        (r"/noti/wsf", WsfNotiHandler),
        (r"/noti/huiju", HJNotiHandler)
    ], debug=True)

    cfg = ConfigParser()
    cfg.read('/home/pyapp/slsh/config/alipay.ini')

    # init logger
    port = cfg.getint('server', 'noti_port')
    log_path = cfg.get('log', 'log_path')
    logger = init_logger("alipay_log", log_path)

    application.listen(port, address='127.0.0.1')
    url = cfg.get('server', 'url')
    key = cfg.get('server', 'key')
    privkey = cfg.get("server", "privkey")
    pubkey = cfg.get("server", "pubkey")
    mchid = cfg.get('server', 'mchid')
    alipay = AliPay(url, mchid, key, privkey, pubkey)
    application.alipay = alipay

    loop = asyncio.get_event_loop()
    redis_1 = loop.run_until_complete(
        aioredis.create_redis(('localhost', 12580), password='PayCore#8bill', db=1, loop=loop)
    )
    application.redis_1 = redis_1
    application.init_with_loop(loop)
    logger.info("alipay noti staring")
    loop.run_forever()
